/*!
 * \file frbyte_buffer.h
 *
 * \brief 数据包移位、读取操作
 *
 * All Rights Reserved Copyright (C) 2014 broada,Co.,Ltd.\n
 * 数据包移位、读取操作
 *
 * \version 2.0
 * \author guojq
 * \date 2014/12/11
 *
 */
#ifndef __FRBYTE_BUFFER_H_
#define __FRBYTE_BUFFER_H_

#include <stdint.h>
#include "frlist.h"

/*! @brief 单个数据块  */
typedef struct __Frbyte_buffer {
    uint32_t pos;                  /*!< 当前的位置 */
    unsigned int ui_len;
    char *p_buf;
} Frbyte_buffer; 

/*! @brief 数据块链表 */
typedef struct __Frbyte_Packet {
    uint32_t pos_index;            /*!< 当前的包在链表中的位置 */
    Frlist_node *p_node_index;     /*!< 当前处理的包的节点 */
    unsigned int ui_all_len;       /*!< 总长度 */
    unsigned int ui_remaining;     /*!< 剩余长度 */
    unsigned int ui_skip_len;      /*!< 跳过的长度 */
    Frlist_header *p_lst_bytebuffer;    
} Frbyte_Packet;

typedef enum __LITTLE_BIG_ENDIAN {
    BYTE_LITTLE_ENDIAN = 0,
    BYTE_BIG_ENDIAN,
} LITTLE_BIG_ENDIAN;

Frbyte_Packet *bytebuff_creat(void);

/*!
 * 关闭数据包链表，释放资源
 *
 * \param pp_packet   (需要释放的packet数据块)
 *
 * \return FR_SUCC:成功\n
 *         FR_FAIL:失败
 *
 *
 */
void bytebuff_free(Frbyte_Packet **pp_packet);

/*!
 * 跳过指定长度的数据(小块数据，指针后移)
 *
 * \param p_packet   (packet数据块)
 * \param len        (跳过的数据长度)
 *
 * \return FR_SUCC:成功\n
 *         FR_FAIL:失败
 *
 *
 */
int bytebuff_skip(Frbyte_Packet *p_packet, size_t len);

/*!
 * 跳过指定长度的数据(大块数据，指针不后移)
 *
 * \param p_packet   (packet数据块)
 * \param len        (跳过的数据长度)
 *
 * \return FR_SUCC:成功\n
 *         FR_FAIL:失败
 *
 *
 */
int bytebuff_set_skip(Frbyte_Packet *p_packet, size_t len);

/*!
 * 数据块位置指针前移
 *
 * \param p_packet   (packet数据块)
 * \param len        (前移的数据长度)
 *
 * \return FR_SUCC:成功\n
 *         FR_FAIL:失败
 *
 *
 */
int bytebuffer_backspace(Frbyte_Packet *p_packet, size_t len);

/*!
 * 取得指定长度的数据 (不移动pos的位置)
 *
 * \param p_packet   (packet数据块)
 * \param ui_len     (取得的长度)
 * \param p_outbuf   (取得的数据内容(内存外面分配))
 *
 * \return FR_SUCC:成功\n
 *         FR_FAIL:失败
 *
 *
 */
int bytebuff_peek_bytes(Frbyte_Packet *p_packet, void *p_outbuf, unsigned int ui_len);

/*!
 * 取得一个int的数据 (不移动pos的位置)
 *
 * \param p_packet   (packet数据块)
 * \param i_len      (取几个字节)
 * \param p_i_data   (取到的int数据(内存外面分配))
 * \param i_endian   (packet里的数据为大端/小端）
 *
 * \return FR_SUCC:成功\n
 *         FR_FAIL:失败
 *
 *
 */
int bytebuff_peek_int(Frbyte_Packet *p_packet, int i_len, uint32_t *p_i_data, LITTLE_BIG_ENDIAN i_endian);

/*!
 * 取得一个long的数据 (不移动pos的位置)
 *
 * \param p_packet   (packet数据块)
 * \param i_len      (取几个字节)
 * \param p_l_data   (取到的long数据(内存外面分配))
 * \param i_endian   (packet里的数据为大端/小端）
 *
 * \return FR_SUCC:成功\n
 *         FR_FAIL:失败
 *
 *
 */
int bytebuff_peek_long(Frbyte_Packet *p_packet, int i_len, uint64_t *p_l_data, LITTLE_BIG_ENDIAN i_endian);

/*!
 * 取得一个short的数据 (不移动pos的位置)
 *
 * \param p_packet   (packet数据块)
 * \param i_len      (取几个字节)
 * \param p_s_data   (取到的short数据(内存外面分配))
 * \param i_endian   (packet里的数据为大端/小端）
 *
 * \return FR_SUCC:成功\n
 *         FR_FAIL:失败
 *
 *
 */
int bytebuff_peek_short(Frbyte_Packet *p_packet, int i_len, uint16_t *p_s_data, LITTLE_BIG_ENDIAN i_endian);

/*!
 * 取得一个char的数据 (不移动pos的位置)
 *
 * \param p_packet   (packet数据块)
 * \param p_char     (取到的char数据)
 *
 * \return FR_SUCC:成功\n
 *         FR_FAIL:失败
 *
 *
 */
int bytebuff_peek_char(Frbyte_Packet *p_packet, uint8_t *p_c_data);

/*!
 * 取得指定长度的数据 (移动pos的位置)
 *
 * \param p_packet   (packet数据块)
 * \param p_outbuf   (取得的数据内容(内存外面分配))
 * \param i_len      (取的长度)
 *
 * \return FR_SUCC:成功\n
 *         FR_FAIL:失败
 *
 *
 */
int bytebuff_get_bytes(Frbyte_Packet *p_packet, void *p_outbuf, unsigned int i_len);

/*!
 * 取得一个int的数据 (移动pos的位置)
 *
 * \param p_packet   (packet数据块)
 * \param i_len      (取几个字节)
 * \param p_i_data   (取到的int数据(内存外面分配))
 * \param i_endian   (packet里的数据为大端/小端）
 *
 * \return FR_SUCC:成功\n
 *         FR_FAIL:失败
 *
 *
 */
int bytebuff_get_int(Frbyte_Packet *p_packet, int i_len, uint32_t *p_i_data, LITTLE_BIG_ENDIAN i_endian);

/*!
 * 取得一个long的数据 (移动pos的位置)
 *
 * \param p_packet   (packet数据块)
 * \param i_len      (取几个字节)
 * \param p_l_data   (取到的long数据(内存外面分配))
 * \param i_endian   (packet里的数据为大端/小端）
 *
 * \return FR_SUCC:成功\n
 *         FR_FAIL:失败
 *
 *
 */
int bytebuff_get_long(Frbyte_Packet *p_packet, int i_len, uint64_t *p_l_data, LITTLE_BIG_ENDIAN i_endian);

/*!
 * 取得一个short的数据 (移动pos的位置)
 *
 * \param p_packet   (packet数据块)
 * \param i_len      (取几个字节)
 * \param p_s_data   (取到的short数据(内存外面分配))
 * \param i_endian   (packet里的数据为大端/小端）
 *
 * \return FR_SUCC:成功\n
 *         FR_FAIL:失败
 *
 *
 */
int bytebuff_get_short(Frbyte_Packet *p_packet, int i_len, uint16_t *p_s_data, LITTLE_BIG_ENDIAN i_endian);

/*!
 * 取得一个char的数据 (移动pos的位置)
 *
 * \param p_packet   (packet数据块)
 * \param p_c_data   (取到的char数据)
 *
 * \return FR_SUCC:成功\n
 *         FR_FAIL:失败
 *
 *
 */
int bytebuff_get_char(Frbyte_Packet *p_packet, uint8_t *p_c_data);

/*!
 * 添加数据到packet数据块
 *
 * \param p_packet   (packet数据块)
 * \param p_buf      (添加的内容)
 * \param ui_buf_len (添加的内容长度)
 *
 * \return FR_SUCC:成功\n
 *         FR_FAIL:失败
 *
 *
 */
int bytebuff_add(Frbyte_Packet *p_packet, char *p_buf, unsigned int ui_buf_len);

/*!
 * 重置packet数据块的处理位置pos
 *
 * \param p_packet   (packet数据块)
 *
 * \return FR_SUCC:成功\n
 *         FR_FAIL:失败
 *
 *
 */
int bytebuff_rewind(Frbyte_Packet *p_packet);

/*!
 * 取得packet数据块的数据总长度
 *
 * \param p_packet   (packet数据块)
 *
 * \return packet数据块的总长度
 *
 *
 */
int bytebuff_length(Frbyte_Packet *p_packet);

/*!
 * 取得packet数据块的剩余长度
 *
 * \param p_packet   (packet数据块)
 *
 * \return packet数据块的剩余长度
 *
 *
 */
int bytebuff_remaining(Frbyte_Packet *p_packet);

/*!
 * 取得packet数据块的当前位置pos
 *
 * \param p_packet   (packet数据块)
 *
 * \return -1:取得失败
 *         packet数据块的当前位置pos
 *
 *
 */
int bytebuff_getPosition(Frbyte_Packet *p_packet);

/*!
 * 设置数据块的读取位置
 *
 * \param p_packet   (packet数据块)
 * \param i_pos      (数据块读取的位置)
 *
 * \return FR_SUCC:成功\n
 *         FR_FAIL:失败
 *
 *
 */
int bytebuff_setPosition(Frbyte_Packet *p_packet, int i_pos);

/*!
 * 把数据块的读取位置设置在最后
 *
 * \param p_packet   (packet数据块)
 *
 * \return FR_SUCC:成功\n
 *         FR_FAIL:失败
 *
 *
 */
int bytebuff_setPositionEnd(Frbyte_Packet *p_packet);

/*!
 * 释放packet数据块处理位置pos前的内容
 *
 * \param p_packet   (packet数据块)
 *
 * \return FR_SUCC:成功\n
 *         FR_FAIL:失败
 *
 *
 */
int bytebuff_truncate(Frbyte_Packet *p_packet);

/*!
 * 二进制类型格式化packet数据块的内容
 *
 * \param p_packet   (packet数据块)
 * \param i_pos      (打印开始的位置)
 * \param i_len      (打印的长度)
 * \param pp_out     (格式化打印的内容)
 *
 * \return FR_SUCC:成功\n
 *         FR_FAIL:失败
 *
 * \note pp_out需要再外面释放内存
 *
 */
int bytebuff_print(Frbyte_Packet *p_packet, int i_pos, int i_len, char **pp_out);

/*!
 * 格式化packet数据块的内容
 *
 * \param p_packet   (packet数据块)
 * \param i_pos      (打印开始的位置)
 * \param i_len      (打印的长度)
 * \param pp_out     (格式化打印的内容)
 *
 * \return FR_SUCC:成功\n
 *         FR_FAIL:失败
 *
 * \note pp_out需要再外面释放内存
 *
 */
//真实数据打印
int bytebuff_show(Frbyte_Packet *p_packet, int i_pos, int i_len, char **pp_out);

/*!
 * 从packet数据块指定位置取指定长度的数据 (位置不移动)
 *
 * \param p_packet   (packet数据块)
 * \param i_pos_from (指定的位置)
 * \param ui_len     (取得的长度)
 * \param p_outbuf   (取得的内容)
 *
 * \return FR_SUCC:成功\n
 *         FR_FAIL:失败
 *
 *
 */
int bytebuff_get_bytes_at(Frbyte_Packet *p_packet, int i_pos_from, unsigned int ui_len, void *p_outbuf);

/*!
 * 从packet数据块指定位置取1个char (位置不移动)
 *
 * \param p_packet   (packet数据块)
 * \param i_pos      (指定的位置)
 * \param p_c_data   (取得的char)
 *
 * \return FR_SUCC:成功\n
 *         FR_FAIL:失败
 *
 *
 */
int bytebuffer_get_at(Frbyte_Packet *p_packet, int i_pos, uint8_t *p_c_data);

/*!
 * 从packet数据块指定位置比较字符串
 *
 * \param p_packet   (packet数据块)
 * \param i_pos      (指定的位置)
 * \param i_endpos   (查找的末尾位置 0:不设置)
 * \param p_substr   (比较的字符串)
 * \param i_sublen   (比较字符串的长度)
 * \param p_i_found  (找到的位置)
 *
 * \return FR_SUCC:成功\n
 *         FR_FAIL:失败
 *
 *
 */
int bytebuff_memstr(Frbyte_Packet *p_packet, int i_pos, int i_endpos, const char *p_substr, int i_sublen, int *p_i_found);

#endif
